﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SmartRoute.Analytics;
using SmartRoute.Randomness;
using SmartRoute.Data;

namespace SmartRoute.Analytics
{
    class Repopulation
    {
        //NOT USED.  FREQUENCY BASED REPOPULATION WHEELS ARE INEFFECTIVE BECAUSE THEY DISREGARD VERY SMALL
        //DIFFERENCES AND SHALLOW GRADIENTS ARE IGNORED
        public static void repopulateUsingFrequencyBasedRoulletteWheel(SmartRoute.Analytics.GenePool pool, List<double> fitnessScores, int wheelSize, int crossoverChance)
        {
            //calculate total score for all
            double totalScore = 0;
            foreach (double score in fitnessScores)
            {
                totalScore += score;
            }

            //calculate how many times each chromosome will be in the new roullette wheel
            int[] frequencyToN = new int[pool.PopSize];
            int nextIndex = 0;
            foreach (double score in fitnessScores)
            {
                frequencyToN[nextIndex] = (int)Math.Floor((score / totalScore) * wheelSize);
                nextIndex++;
            }

            Chromosome[] wheel = new Chromosome[wheelSize];

            //nextindex used to place elements in the wheel
            nextIndex = 0;
            for (int i = 0; i < frequencyToN.Length; i++)
            {
                for (int j = 0; j < frequencyToN[i]; j++)
                {
                    wheel[nextIndex] = (Chromosome)pool.Population[i].Clone();
                    nextIndex++;
                }
            }

            bool foundWheelEnd = false;
            int wheelEnd = -1;
            int nextInd = 0;
            while (foundWheelEnd == false)
            {
                if (wheel[nextInd] == null)
                {
                    foundWheelEnd = true;
                    wheelEnd = nextInd;
                    
                }
                nextInd++;
            }

            //use the wheel to repopulate
            List<Chromosome> newPool = new List<Chromosome>();

            int willcrossover = -1;
            int crossoverLocation = -1;

            for (int i = 0; i < pool.PopSize; i++)
            {
                willcrossover = pool.Rand.fromTo(0, 99);
                if (willcrossover > crossoverChance)
                {
                    int firstIndex = pool.Rand.fromTo(0, wheelEnd-1);
                    int secondIndex = pool.Rand.fromTo(0, wheelEnd-1);
                    crossoverLocation = pool.Rand.fromTo(0, pool.NumberStops - 1);
                    Chromosome temp = (Chromosome)wheel[firstIndex].Clone();
                    for (int j = crossoverLocation; j < temp.Stops.Count; j++)
                    {
                        temp.Stops[j] = (Stop)wheel[secondIndex].Stops[j].Clone();
                    }
                    newPool.Add(temp);

                }
                else
                {
                    nextIndex = pool.Rand.fromTo(0, wheelEnd - 1);
                    Chromosome next = (Chromosome)wheel[nextIndex].Clone();
                    newPool.Add(next);
                }
            }
            pool.Population = newPool;
        }

        
    }
}
